資料變更很少單獨發生:一筆轉帳必須從一個帳戶扣款並向另一個帳戶入帳,一張訂單必須保留庫存並記錄付款。如果系統中途停止,資料庫將停留在一個從未存在過的世界。一個 交易 正是資料庫對此問題的解答——一連串一個或多個操作,資料庫將其視為 單一且不可分割的工作單位。
全有或全無
在交易內部,每個操作都屬於同一個結果。資料庫絕不會呈現只完成部分交易的完成狀態。經典的例子是兩個銀行帳戶之間的轉帳:先扣減來源帳戶的餘額,再增加目的地帳戶的餘額。如果只有第一步成功,錢就會消失;如果只有第二步成功,錢就會憑空出現。將這兩個步驟包裝在一個交易中,就能消除這兩種可能性。
這種全有或全無的保證稱為 原子性。 提交 是讓交易的變更永久生效的動作;從未提交的交易不會留下任何痕跡。 持久性 補上最後一塊拼圖:一旦提交成功返回,即使機器在片刻後斷電,該變更仍會保留。
交易是一道邊界
將交易想像成圍繞一組敘述句所劃出的邊界會很有幫助。在邊界之前與之後,資料都滿足結構所施加的規則。在邊界之內,會存在中間狀態——一個帳戶已經扣款,而另一個尚未入帳——但這些狀態僅屬於該交易。其他工作階段中較晚執行的敘述句不會將其視為事實。
同時完成兩項任務
因此,交易要完成兩項任務。第一項是 失敗處理:如果行程當機、連線中斷,或某個敘述句發生錯誤,資料庫可以還原交易開始前所存在的狀態。第二項是 可見性控制:當工作進行中時,其他讀取者會被隔絕於未完成的結果之外。這兩項任務相關但並不相同——原子性決定變更是否被保留,而可見性則由隔離性所控制,隔離性是控制並行交易之間能看見彼此多少內容的設定。
讓工作單位保持在同一個連線上
交易狀態屬於某個連線或工作階段,因此開啟交易的敘述句與結束交易的提交必須在同一個連線上執行。許多驅動程式也運作於 autocommit 模式,其中每個敘述句各自構成一個交易——多敘述句的工作單位需要關閉 autocommit,或明確地啟動交易。
